#include "../StdAfx.h"
#include "../MemPtr.h"
#include "../ComPropVariant.h"
#include "ArchiveItemMap.h"
#include "SevenZipStream.h"
#include "SevenZipArchive.h"

using namespace SevenZip;

SevenZip::CSevenZipArchive::CSevenZipArchive()
	: _RootFolder(NULL)
{
}

SevenZip::CSevenZipArchive::~CSevenZipArchive()
{
	if (_RootFolder != NULL)
	{
		delete _RootFolder;
	}
}

STDMETHODIMP SevenZip::CSevenZipArchive::InitializeFromPath(const CSevenZipFactoryPtr & Factory, LPCWSTR Path)
{
	HRESULT hr;
	CComPtr<IStream> Stream;

	if (SUCCEEDED(hr = ::SHCreateStreamOnFileEx(Path, 
	                                            STGM_READ | STGM_SHARE_DENY_WRITE,
				 						        FILE_ATTRIBUTE_NORMAL,
				 						        FALSE,
										        NULL,
										        &Stream)))
	{
		hr = InitializeFromStream(Factory, Path, Stream);
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipArchive::InitializeFromPIDL(const SevenZip::CSevenZipFactoryPtr & Factory, PCIDLIST_ABSOLUTE ItemIDList)
{
	WCHAR   path[MAX_PATH];
	HRESULT hr = E_INVALIDARG;

	if (::SHGetPathFromIDListW(ItemIDList, path))
	{
		if (SUCCEEDED(hr = InitializeFromPath(Factory, path)))
		{
		}
	}
	
	return hr;
}

STDMETHODIMP SevenZip::CSevenZipArchive::InitializeFromStream(const CSevenZipFactoryPtr &  Factory, 
															  const CStringW &             FileName,
															  const CComPtrBase<IStream> & Stream)
{
	HRESULT hr;
	CComPtr<CSevenZipStream> InStream;

	if (SUCCEEDED(hr = CoCreate(InStream)))
	{
		if (SUCCEEDED(hr = InStream->Initialize(Stream)))
		{
			if (SUCCEEDED(hr = InStream.QueryInterface(&_InStream)))
			{
				_Name = FileName;
				hr = Open(Factory);
			}
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipArchive::Open(const CSevenZipFactoryPtr & Factory)
{
	HRESULT hr;
	CAtlArray<const CSevenZipFormat*> Formats; 

	LPCWSTR Extension = ::PathFindExtension(_Name);
	
	if (SUCCEEDED(hr = Factory->FindFormatByExtension(Extension, Formats)))
	{
		if (Formats.GetCount() != 1)
		{
			return E_FAIL;
		}

		if (SUCCEEDED(hr = Formats.GetAt(0)->CreateInstance(_InArchive)))
		{
			if (SUCCEEDED(hr = _InArchive->Open(_InStream, NULL, NULL)))
			{
				hr = GetItems();
			}
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipArchive::GetItems()
{
	HRESULT hr = E_FAIL;

	if (_InArchive != NULL)
	{
		UINT32 ItemCount;

		if (SUCCEEDED(hr = _InArchive->GetNumberOfItems(&ItemCount)))
		{
			CSevenZipArchiveItemMap Map(_InArchive);

			for (UINT32 i = 0; SUCCEEDED(hr) && (i < ItemCount); i++)
			{
				hr = Map.AddItem(i);
			}

			if (SUCCEEDED(hr))
			{
				_RootFolder = Map.GetRoot();
			}
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipArchive::Extract()
{
	return E_NOTIMPL;
}
